{#if realm === 'home'}
  <h2 class="sr-only">{intl.composeStatus}</h2>
{/if}
<ComposeFileDrop {realm} >
  <div class="{computedClassName} {hideAndFadeIn}">
    <ComposeAuthor {realm} {dialogId} />
    {#if contentWarningShown}
      <div class="compose-content-warning-wrapper"
           transition:slide="{duration: 333}">
        <ComposeContentWarning {realm} {contentWarning} />
      </div>
    {/if}
    <ComposeInput {realm} {text} {autoFocus} on:postAction="doPostStatus()" />
    <ComposeLengthGauge {length} {overLimit} />
    <ComposeAutosuggest {realm} {text} {dialogId} />
    {#if poll && poll.options && poll.options.length}
      <div class="compose-poll-wrapper"
           transition:slide="{duration: 333}">
        <ComposePoll {realm} {poll} />
      </div>
    {/if}
    <ComposeToolbar {realm} {postPrivacy} {media} {contentWarningShown} {text} {poll} />
    <ComposeLengthIndicator {length} {overLimit} />
    <ComposeMedia {realm} {media} />
    <ComposeMediaSensitive {realm} {media} {sensitive} {contentWarning} {contentWarningShown} />
  </div>
</ComposeFileDrop>
<ComposeStickyButton {showSticky}
                     {overLimit}
                     {hideAndFadeIn}
                     on:postAction="doPostStatus()" />
{#if !hideBottomBorder}
  <div class="compose-box-border-bottom {hideAndFadeIn}"></div>
{/if}

<style>
  .compose-box {
    border-radius: 4px;
    padding: 20px 20px 0 20px;
    display: grid;
    align-items: flex-start;
    grid-template-areas:
      "avatar name        handle      handle"
      "avatar cw          cw          cw"
      "avatar input       input       input"
      "avatar gauge       gauge       gauge"
      "avatar autosuggest autosuggest autosuggest"
      "avatar poll        poll        poll"
      "avatar toolbar     toolbar     length"
      "avatar media       media       media"
      "avatar sensitive   sensitive   sensitive";
    grid-template-columns: min-content minmax(0, max-content) 1fr 1fr;
    position: relative;
  }

  .compose-box.direct-reply {
    background-color: var(--status-direct-background);
  }

  :global(.compose-box-fade-in) {
    transition: opacity 0.2s linear; /* main page reveal */
  }

  .compose-box-border-bottom {
    height: 1px;
    background: var(--main-border);
    width: 100%;
  }

  .compose-content-warning-wrapper {
    grid-area: cw;
  }

  .compose-poll-wrapper {
    grid-area: poll;
  }

  @media (max-width: 767px) {
    .compose-box {
      padding: 10px 10px 0 10px;
    }

    .compose-box-realm-dialog {
      overflow-x: hidden;
    }
  }

  @media (max-width: 240px) {
    .compose-box {
      padding: 10px 5px 0 5px;
    }
  }
</style>
<script>
  import ComposeToolbar from './ComposeToolbar.html'
  import ComposeLengthGauge from './ComposeLengthGauge.html'
  import ComposeLengthIndicator from './ComposeLengthIndicator.html'
  import ComposeAuthor from './ComposeAuthor.html'
  import ComposeInput from './ComposeInput.html'
  import ComposeStickyButton from './ComposeStickyButton.html'
  import ComposeMedia from './ComposeMedia.html'
  import ComposeContentWarning from './ComposeContentWarning.html'
  import ComposeFileDrop from './ComposeFileDrop.html'
  import ComposeAutosuggest from './ComposeAutosuggest.html'
  import ComposePoll from './ComposePoll.html'
  import ComposeMediaSensitive from './ComposeMediaSensitive.html'
  import { measureText } from '../../_utils/measureText.js'
  import { POST_PRIVACY_OPTIONS } from '../../_static/statuses.js'
  import { store } from '../../_store/store.js'
  import { slide } from '../../_transitions/slide.js'
  import { postStatus, insertHandleForReply, setReplySpoiler, setReplyVisibility } from '../../_actions/compose.js'
  import { classname } from '../../_utils/classname.js'
  import { POLL_EXPIRY_DEFAULT } from '../../_static/polls.js'
  import { scheduleIdleTask } from '../../_utils/scheduleIdleTask.js'

  export default {
    oncreate () {
      const { realm, replySpoiler, replyVisibility } = this.get()
      if (realm !== 'home' && realm !== 'dialog') {
        // if this is a reply, populate the handle immediately
        /* no await */ insertHandleForReply(realm)
      }

      if (replySpoiler) {
        // default spoiler is same as the replied-to status
        setReplySpoiler(realm, replySpoiler)
      }

      if (replyVisibility) {
        // make sure the visibility is consistent with the replied-to status
        setReplyVisibility(realm, replyVisibility)
      }
    },
    components: {
      ComposeAuthor,
      ComposeToolbar,
      ComposeLengthGauge,
      ComposeLengthIndicator,
      ComposeInput,
      ComposeStickyButton,
      ComposeMedia,
      ComposeContentWarning,
      ComposeFileDrop,
      ComposeAutosuggest,
      ComposePoll,
      ComposeMediaSensitive
    },
    data: () => ({
      size: undefined,
      isReply: false,
      autoFocus: false,
      hideBottomBorder: false,
      hidden: false,
      dialogId: undefined,
      aboutToPostStatus: false
    }),
    store: () => store,
    computed: {
      computedClassName: ({ overLimit, realm, size, postPrivacyKey, isReply }) => (classname(
        'compose-box',
        `compose-box-realm-${realm}`,
        overLimit && 'over-char-limit',
        isReply && postPrivacyKey === 'direct' && 'direct-reply'
      )),
      hideAndFadeIn: ({ hidden }) => (classname(
        'compose-box-fade-in',
        hidden && 'hidden'
      )),
      showSticky: ({ realm }) => realm === 'home',
      composeData: ({ $currentComposeData, realm }) => $currentComposeData[realm] || {},
      text: ({ composeData }) => composeData.text || '',
      media: ({ composeData }) => composeData.media || [],
      poll: ({ composeData }) => composeData.poll,
      inReplyToId: ({ composeData }) => composeData.inReplyToId,
      postPrivacy: ({ postPrivacyKey }) => POST_PRIVACY_OPTIONS.find(_ => _.key === postPrivacyKey),
      defaultPostPrivacyKey: ({ $currentVerifyCredentials }) => (
        ($currentVerifyCredentials && $currentVerifyCredentials.source.privacy) || 'public'
      ),
      postPrivacyKey: ({ composeData, defaultPostPrivacyKey }) => composeData.postPrivacy || defaultPostPrivacyKey,
      textLength: ({ text }) => measureText(text),
      contentWarningLength: ({ contentWarning }) => measureText(contentWarning),
      length: ({ textLength, contentWarningLength, contentWarningShown }) => (
        textLength + (contentWarningShown ? contentWarningLength : 0)
      ),
      overLimit: ({ length, $maxStatusChars }) => length > $maxStatusChars,
      contentWarningShown: ({ composeData }) => composeData.contentWarningShown,
      contentWarning: ({ composeData }) => composeData.contentWarning || '',
      sensitive: ({ composeData }) => !!composeData.sensitive
    },
    transitions: {
      slide
    },
    methods: {
      async doPostStatus () {
        const { aboutToPostStatus } = this.get()
        const { postingStatus } = this.store.get()
        if (aboutToPostStatus || postingStatus) { // do nothing if the user rapidly taps the Ctrl-Enter key
          console.log('ignored post command', { aboutToPostStatus, postingStatus })
          return
        }
        // The reason we add a scheduleIdleTask delay here is because we also use scheduleIdleTask
        // in ComposeInput.html to debounce the input events. If the user is very fast at typing
        // at their keyboard and quickly presses Ctrl+Enter or the "Toot" button then there could
        // be a race condition where not all of their status is posted.
        this.set({ aboutToPostStatus: true })
        scheduleIdleTask(() => {
          this.set({ aboutToPostStatus: false })
          this.doPostStatusAfterDelay()
        })
      },
      doPostStatusAfterDelay () {
        const {
          text,
          media,
          postPrivacyKey,
          contentWarning,
          realm,
          overLimit,
          inReplyToUuid, // typical replies, using Pinafore-specific uuid
          inReplyToId, // delete-and-redraft replies, using standard id
          poll,
          sensitive
        } = this.get()
        const mediaIds = media.map(_ => _.data.id)
        const mediaDescriptions = media.map(_ => _.description)
        const mediaFocalPoints = media.map(_ => [_.focusX, _.focusY])
        const inReplyTo = inReplyToId || ((realm === 'home' || realm === 'dialog') ? null : realm)

        if (overLimit || (!text && !media.length)) {
          return // do nothing if invalid
        }

        const hasPoll = poll && poll.options && poll.options.length
        if (hasPoll) {
          // validate poll
          if (poll.options.length < 2 || !poll.options.every(Boolean)) {
            return
          }
        }

        // convert internal poll format to the format Mastodon's REST API uses
        const pollToPost = hasPoll && {
          expires_in: (poll.expiry || POLL_EXPIRY_DEFAULT).toString(),
          multiple: !!poll.multiple,
          options: poll.options
        }

        /* no await */ postStatus(realm, text, inReplyTo, mediaIds,
          sensitive, contentWarning, postPrivacyKey,
          mediaDescriptions, inReplyToUuid, pollToPost,
          mediaFocalPoints)
      }
    }
  }
</script>
